package robocup.component;

import robocup.component.geometry.Circle;
import robocup.component.geometry.Vektor;
import robocup.component.worldobjects.Flag;
import robocup.component.worldobjects.Line;

/**
 * All server params are remembered here. These params are received from the
 * server after initialization of the agent, and are the same for all players.
 * Therefore a static class is used. These can also be found in the server.conf
 * file, which is automatically created by the server in
 * &lt;home&gt;/.rcssserver/ on first startup. <br>
 * <br>
 * Note that these values can't really be changed by the agent. If the listed
 * values are not equal to those sent by the server, the agent may expect a
 * different system behaviour and its calculations may subsequently be wrong.
 * Hence changing these values should only be done after receiving the correct
 * values from the server.
 */
public class SConf {

  /**
   * The SConf is implemented as singleton. Using the default constructor
   * <code>new SConf()</code> creates a server configuration with the default
   * values.
   */
  private static SConf instance = new SConf();

  /**
   * Retrieves a reference to the global SConf instance.
   * 
   * @return the server configuration
   */
  public static SConf getInstance() {

    return SConf.instance;
  }

  /**
   * This method sets a new server configuration.
   * 
   * @param conf
   *          the new configuration
   */
  public static void setInstance(final SConf conf) {

    SConf.instance = conf;
  }

  /**
   * <code>SConf</code> constructor Server specific constants, which have
   * effect on various calculations.
   */
  private SConf() {

    this.initFlagAreas();
  }

  /**
   * The default position of the center of the opponents goal.
   */
  public final Vektor  GOAL_POS_OTHER           = new Vektor(Vektor.XY, 0, 52.5);

  /**
   * The default position of the left post of the opponents goal.
   */
  public final Vektor  GOAL_POST_LEFT_OTHER     = new Vektor(Vektor.XY, -7,
                                                    52.5);

  /**
   * The default position of the right post of the opponents goal.
   */
  public final Vektor  GOAL_POST_RIGHT_OTHER    = new Vektor(Vektor.XY, +7,
                                                    52.5);

  /**
   * The default position of the left post of the own goal.
   */
  public final Vektor  GOAL_POST_LEFT_OWN       = new Vektor(Vektor.XY, -7,
                                                    -52.5);

  /**
   * The default position of the right post of the own goal.
   */
  public final Vektor  GOAL_POST_RIGHT_OWN      = new Vektor(Vektor.XY, +7,
                                                    -52.5);

  /**
   * The default position of the center of the own goal.
   */
  public final Vektor  GOAL_POS_OWN             = new Vektor(Vektor.XY, 0,
                                                    -52.5);

  /**
   * The default position of the left corner of the own side.
   */
  public final Vektor  CORNER_LEFT_OWN          = new Vektor(Vektor.XY, -34,
                                                    -52.5);

  /**
   * The default position of the right corner of the own side.
   */
  public final Vektor  CORNER_RIGHT_OWN         = new Vektor(Vektor.XY, 34,
                                                    -52.5);

  /**
   * The default position of the left corner of the opponents side.
   */
  public final Vektor  CORNER_LEFT_OTHER        = new Vektor(Vektor.XY, -34,
                                                    52.5);

  /**
   * The default position of the right corner of the opponents side.
   */
  public final Vektor  CORNER_RIGHT_OTHER       = new Vektor(Vektor.XY, 34,
                                                    52.5);

  /**
   * The offline coach (trainer) is allowed or not
   */
  public boolean       COACH                    = false;

  /**
   * The maximal distance, in which a message from a player can be heared.
   */
  public double        AUDIO_CUT_DIST           = 50.0;

  /**
   * Backpasses are recognized by the referee (1.0) of not (0)
   */
  public double        BACK_PASSES              = 1.0;

  /**
   * The maximum ball acceleration factor (default 2.7)
   */
  public double        BALL_ACC_MAX             = 2.7;

  /**
   * The balls decau factor (default 0.94)
   */
  public double        BALL_DECAY               = .94;

  /**
   * The balls noise factor (default 0.05)
   */
  public double        BALL_RAND                = .05;

  /**
   * The balls size/radius (default 0.085m)
   */
  public double        BALL_SIZE                = .085;

  /**
   * The maximal ball-speed (default 2.7)
   */
  public double        BALL_SPEED_MAX           = 3.0;

  /**
   * The balls weight (default 0.2)
   */
  public double        BALL_WEIGHT              = .2;

  /**
   * 
   */
  public double        CATCH_BAN_CYCLE          = 5.0;

  /**
   * The probability for the goalie to catch the ball (default 1)
   */
  public double        CATCH_PROBABILITY        = 1.0;

  /**
   * The length of the goalies catchable area (default 2.0m)
   */
  public double        CATCHABLE_AREA_L         = 1.2;

  /**
   * The width of the goalies catchable area (default 1.0m)
   */
  public double        CATCHABLE_AREA_W         = 1.0;

  /**
   * The maximum allowed angle of the goalie to catch the ball (default 180)
   */
  public double        CATCH_MAXMOMENT          = 180.0;

  /**
   * The minimum allowed angle of the goalie to catch the ball (default -180)
   */
  public double        CATCH_MINMOMENT          = -180.0;

  /**
   * 
   */
  public double        CKICK_MARGIN             = 1.0;

  /**
   * The amount of cycles, which must be waited before the next clang message is
   * accepted by the server (freeform messages have an own window) (default 300)
   */
  public int           CLANG_WIN_SIZE           = 300;

  /**
   * The time in cycles, after which the ball is dropped, if no action happen in
   * standard playmodes (default 200)
   */
  public double        DROP_BALL_TIME           = 200.0;

  /**
   * Effort decrease step, if the stamina is lower than STAMINA_MAX *
   * EFFORT_DEC_THR (default 0.005)
   */
  public double        EFFORT_DEC               = .005;

  /**
   * The threshold factor for the stamina, which indicates a decrease of the
   * players effort, if stamina is lower than STAMINA_MAX * EFFORT_DEC_THR.
   * (default 0.3)
   */
  public double        EFFORT_DEC_THR           = .3;

  /**
   * Effort increase step, if the stamina is lower than STAMINA_MAX *
   * EFFORT_INC_THR (default 0.01).
   */
  public double        EFFORT_INC               = .01;

  /**
   * The threshold factor for the stamina, which indicates an increase of the
   * players effort, if stamina is lower than STAMINA_MAX * EFFORT_INC_THR.
   * (default 0.6).
   */
  public double        EFFORT_INC_THR           = .6;

  /**
   * The default effort value (1.0)
   */
  public double        EFFORT_INIT              = 1.0;

  /**
   * If set to 1, offside is recognized by the referee after kickoff (default 1)
   */
  public double        FORBID_KICK_OFF_OFFSIDE  = 1.0;

  /**
   * If set to 1, free-kick-fauls are recognized by the referee (e.g. the free
   * kick is intercepted by the executing agent itself). (default 1)
   */
  public double        FREE_KICK_FAULTS         = 1.0;

  /**
   * The time in cycles, which is waited before a freeform message is forwarded
   * to the agents (default 20)
   */
  public int           FREEFORM_SEND_PERIOD     = 20;

  /**
   * The time in cycles, which is waited before a new freeform message is
   * accepted by the server (default 600)
   */
  public int           FREEFORM_WAIT_PERIOD     = 600;

  /**
   * The width of a goal (default 14.02)
   */
  public double        GOAL_WIDTH               = 14.02;

  /**
   * The maximum number of moves allowed to execute by the goalie after catching
   * a ball (default 2)
   */
  public int           GOALIE_MAX_MOVES         = 2;

  /**
   * The half-time length in cycles (default 30, in official tournaments 300)
   */
  public double        HALF_TIME                = 30.0;

  /**
   * The step by which the actual allowed number of messages per team is
   * decreased on receivement (default 1)
   */
  public double        HEAR_DECAY               = 1.0;

  /**
   * The step by which the actual allowed number of messages is increased each
   * cycle (default 1)
   */
  public double        HEAR_INC                 = 1.0;

  /**
   * The maximum number of messages allowed to receive per team each cycle. This
   * means, that a player can hear at most two times HEAR_MAX messages per
   * cycle. (default 1)
   */
  public double        HEAR_MAX                 = 1.0;

  /**
   * The time in cycles, which is waited, before the game is set to play-mode
   * kick-off (default 100)
   */
  public double        KICK_OFF_WAIT            = 100.0;

  /**
   * The kick-power rate for a player (default 0.027), which determines the
   * acceleration of the ball.
   */
  public double        KICK_POWER_RATE          = .027;

  /**
   * (default 0.1)
   */
  public double        MARGIN_NOISE             = .1;

  /**
   * 
   */
  public double        MAX_GOAL_KICKS           = 3.0;

  /**
   * The maximum angle an agent can set to a turn command (default 180)
   */
  public double        MAXMOMENT                = 180.0;

  /**
   * The maximum neck-angle (default 90)
   */
  public double        MAXNECKANG               = 90.0;

  /**
   * The maximum angle an agent can set to a turnneck command (default 180)
   */
  public double        MAXNECKMOMENT            = 180.0;

  /**
   * The maximum dash-power an agent can use (default 100)
   */
  public double        MAXPOWER                 = 100.0;

  /**
   * The minimum angle an agent can set to a turn command (default -180)
   */
  public double        MINMOMENT                = -180.0;

  /**
   * The minimum neck-angle (default 90)
   */
  public double        MINNECKANG               = -90.0;

  /**
   * The minimum angle an agent can set to a turnneck command (default -180)
   */
  public double        MINNECKMOMENT            = -180.0;

  /**
   * The minimum dash-power an agent can use (default -100). Note that negative
   * values indicate backward dashing.
   */
  public double        MINPOWER                 = -100.0;

  /**
   * The maximum acceleration factor for a player (default 1)
   */
  public double        PLAYER_ACCEL_MAX         = 1.0;

  /**
   * The players random movement noise (default 0.1)
   */
  public double        PLAYER_RAND              = 0.1;

  /**
   * The players weight (default 60)
   */
  public double        PLAYER_WEIGHT            = 60.0;

  /**
   * The number of cycles a point-to action must last at minimum (default 5)
   */
  public int           POINT_TO_BAN             = 5;

  /**
   * The number of cycles a point-to action last, if not renewed (default 20)
   */
  public int           POINT_TO_DURATION        = 20;

  /**
   * The step by which the recovery-value is decreased, if the corresponding
   * stamina threshold is underrun. Note that recovery will not increase with
   * high stamina. (default 0.002)
   */
  public double        RECOVER_DEC              = .002;

  /**
   * The factor for the stamina value, which determines the recovery-decrease
   * threshold (default 0.3)
   */
  public double        RECOVER_DEC_THR          = .3;

  /**
   * The value, which is set to recovery on reinit (after half-time) (default 1)
   */
  public double        RECOVER_INIT             = 1.0;

  /**
   * The maximum recovery value (default 1)
   */
  public double        RECOVER_MAX              = 1.0;

  /**
   * The minimum recovery value (default 0.5)
   */
  public double        RECOVER_MIN              = 0.5;

  /**
   * upper limit of the number of online coach's message (default 128)
   */
  public int           SAY_COACH_COUNT_MAX      = 128;

  /**
   * The number of allowed characters in a freeform message (default 128)
   */
  public int           SAY_COACH_MSG_SIZE       = 128;

  /**
   * The number of allowed characters in a player say action (default 10)
   */
  public int           SAY_MSG_SIZE             = 10;

  /**
   * The interval in milliseconds, after which a new sensebody info is send by
   * the server (default 100)
   */
  public int           SENSE_BODY_STEP          = 100;

  /**
   * The maximum stamina value of a player (default 8000)
   */
  public double        STAMINA_MAX              = 8000.0;

  /**
   * The velocity, by which the ball is set to speed 0 (default 0.01)
   */
  public double        STOPPED_BALL_VEL         = 0.01;

  /**
   * The maximum distance a player can tackle backwards (default 0.5)
   */
  public double        TACKLE_BACK_DIST         = 0.0;

  /**
   * The number of cycles an player is disabled after tackling (default 10)
   */
  public int           TACKLE_CYCLES            = 10;

  /**
   * The maximum distance a player can tackle forward (default 2.0)
   * TODO: check, if this is true
   */
  public double        TACKLE_DIST              = 2.0;

  /**
   * A factor for determining the tackle-success probability. Depends on the
   * distance to the ball (default 6.0) Note, that this value is an exponent!
   */
  public double        TACKLE_EXPONENT          = 6.0;

  /**
   * The tackle power rate, which determines the acceleration of a tackled ball
   * (default 0.027)
   * TODO: check, if this is true
   */
  public double        TACKLE_POWER_RATE        = 0.027;

  /**
   * Since: v12. The maximum tackle power, whic is only achieved
   * when tackling forward.
   */
  public double 	   MAX_TACKLE_POWER			= 100;
  
  /**
   * Since: v12. The minimum tackle power, formerly named:
   * min_tackle_power. This one is used to calculate the
   * effective tackle power.
   */
  public double 	   MAX_BACK_TACKLE_POWER    = 0;
  
  
  /**
   * The width, in which tackling generally is allowed. Note that for distant
   * balls, the probability of successful tacklings is null, although the ball
   * is within the tackle area. (default 1.0m)
   * 
   * TODO: check, if this is true
   */
  public double        TACKLE_WIDTH             = 1.0;

  /**
   * The basic visible angle (default 90).
   * 
   * TODO: check this
   */
  public double        VISIBLE_ANGLE            = 120.0;

  /**
   * This distance in meter, in which a player can "sense" objects (default 3.0)
   */
  public double        VISIBLE_DISTANCE         = 3.0;

  /**
   * Determines if offside is recognized by the referee (default 1|true)
   */
  public int           USE_OFFSIDE              = 1;

  /**
   * The length of one field-half (default 52.5)
   */
  public double        half_length              = 52.5;                                  // Half

  /**
   * The width of one field-half (default 34)
   */
  public double        half_width               = 34;                                    // Half

  /**
   * The width of a half goal (default 7.01)
   */
  public double        half_goal_width          = 7.01;                                  // Half

  /**
   * The length of the penalty area (default 16.5)
   */
  public double        penalty_length           = 16.5;                                  // Penalty

  /**
   * The width of the penalty area (default 20.175)
   */
  public double        half_penalty_width       = 20.175;                                // Half

  /**
   * The distance from the field border to the physical field boundary (default
   * 5)
   */
  private final double       boundary_distance        = 5.0;                                   // Boundary

  /**
   * Marker for horizontal width 10m (flags use them)
   */
  private double       half_horizontal_10_width = 10.0;                                  // Half

  /**
   * Marker for horizontal width 20m (flags use them)
   */
  private double       half_horizontal_20_width = 20.0;                                  // Half

  /**
   * Marker for horizontal width 30m (flags use them)
   */
  private double       half_horizontal_30_width = 30.0;                                  // Half

  /**
   * Marker for vertical length 10m (flags use them)
   */
  private double       half_vertical_10_length  = 10.0;                                  // Half

  /**
   * Marker for vertical length 20m (flags use them)
   */
  private double       half_vertical_20_length  = 20.0;                                  // Half

  /**
   * Marker for vertical length 30m (flags use them)
   */
  private double       half_vertical_30_length  = 30.0;                                  // Half

  /**
   * Marker for vertical length 40m (flags use them)
   */
  private double       half_vertical_40_length  = 40.0;                                  // Half

  /**
   * Marker for vertical length 50m (flags use them)
   */
  private double       half_vertical_50_length  = 50.0;                                  // Half

  /**
   * All known flags. Note that these flags refer to the servers coordinate
   * space and hence must not be turned. <br>
   * <ol start=0>
   * <li>CENTER = (flag c)
   * <li>CENTER_LEFT = (flag c t)
   * <li>CENTER_RIGHT = (flag c b)
   * <li>PENALTY_CENTER_TOP = (flag p r c)
   * <li>PENALTY_LEFT_TOP = (flag p r t)
   * <li>PENALTY_RIGHT_TOP = (flag p r b)
   * <li>PENALTY_CENTER_BOTTOM = (flag p l c)
   * <li>PENALTY_LEFT_BOTTOM = (flag p l t)
   * <li>PENALTY_RIGHT_BOTTOM = (flag p l b)
   * <li>GOAL_TOP = (goal r)
   * <li>GOAL_LEFT_TOP = (flag g r t)
   * <li>GOAL_RIGHT_TOP = (flag g r b)
   * <li>GOAL_BOTTOM = (goal l)
   * <li>GOAL_LEFT_BOTTOM = (flag g l t)
   * <li>GOAL_RIGHT_BOTTOM = (flag b l b) isn't it (flag g l b)?
   * <li>CORNER_LEFT_TOP = (flag r t)
   * <li>CORNER_RIGHT_TOP = (flag r b)
   * <li>CORNER_LEFT_BOTTOM = (flag l t)
   * <li>CORNER_RIGHT_BOTTOM = (flag l b)
   * <li>BOUND_TOP = (flag r 0)
   * <li>BOUND_TOP_LEFT_10 = (flag r t 10)
   * <li>BOUND_TOP_RIGHT_10 = (flag r b 10)
   * <li>BOUND_TOP_LEFT_20 = (flag r t 20)
   * <li>BOUND_TOP_RIGHT_20 = (flag r b 20)
   * <li>BOUND_TOP_LEFT_30 = (flag r t 30)
   * <li>BOUND_TOP_RIGHT_30 = (flag r b 30)
   * <li>BOUND_BOTTOM = (flag l 0)
   * <li>BOUND_BOTTOM_LEFT_10 = (flag l t 10)
   * <li>BOUND_BOTTOM_RIGHT_10 = (flag l b 10)
   * <li>BOUND_BOTTOM_LEFT_20 = (flag l t 20)
   * <li>BOUND_BOTTOM_RIGHT_20 = (flag l b 20)
   * <li>BOUND_BOTTOM_LEFT_30 = (flag l t 30)
   * <li>BOUND_BOTTOM_RIGHT_30 = (flag l b 30)
   * <li>BOUND_LEFT = (flag t 0)
   * <li>BOUND_LEFT_BOTTOM_10 = (flag t l 10)
   * <li>BOUND_LEFT_TOP_10 = (flag t r 10)
   * <li>BOUND_LEFT_BOTTOM_20 = (flag t l 20)
   * <li>BOUND_LEFT_TOP_20 = (flag t r 20)
   * <li>BOUND_LEFT_BOTTOM_30 = (flag t l 30)
   * <li>BOUND_LEFT_TOP_30 = (flag t r 30)
   * <li>BOUND_LEFT_BOTTOM_40 = (flag t l 40)
   * <li>BOUND_LEFT_TOP_40 = (flag t r 40)
   * <li>BOUND_LEFT_BOTTOM_50 = (flag t l 50)
   * <li>BOUND_LEFT_TOP_50 = (flag t r 50)
   * <li>BOUND_RIGHT = (flag b 0)
   * <li>BOUND_RIGHT_BOTTOM_10 = (flag b l 10)
   * <li>BOUND_RIGHT_TOP_10 = (flag b r 10)
   * <li>BOUND_RIGHT_BOTTOM_20 = (flag b l 20)
   * <li>BOUND_RIGHT_TOP_20 = (flag b r 20)
   * <li>BOUND_RIGHT_BOTTOM_30 = (flag b l 30)
   * <li>BOUND_RIGHT_TOP_30 = (flag b r 30)
   * <li>BOUND_RIGHT_BOTTOM_40 = (flag b l 40)
   * <li>BOUND_RIGHT_TOP_40 = (flag b r 40)
   * <li>BOUND_RIGHT_BOTTOM_50 = (flag b l 50)
   * <li>BOUND_RIGHT_TOP_50 = (flag b r 50)
   * </ol>
   */
  public final Flag[] flags                    
   = {
      // CENTER = (flag c)
      new Flag(-1, 5, new Vektor(
          Vektor.XY, 0.0, 0.0)),
      // CENTER_LEFT = (flag c t)
      new Flag(-1, 51, new Vektor(
          Vektor.XY,
          -this.half_width, 0.0)),
      // CENTER_RIGHT = (flag c b)
      new Flag(-1, 52, new Vektor(
          Vektor.XY, this.half_width,
          0.0)),
      
      // PENALTY_CENTER_TOP = (flag p
      // r c)
      new Flag(
          -1,
          745,
          new Vektor(
              Vektor.XY,
              0.0,
              this.half_length - this.penalty_length)),
      // PENALTY_LEFT_TOP = (flag p r
      // t)
      new Flag(
          -1,
          741,
          new Vektor(
              Vektor.XY,
              -this.half_penalty_width,
              this.half_length - this.penalty_length)),
      // PENALTY_RIGHT_TOP = (flag p r
      // b)
      new Flag(
          -1,
          742,
          new Vektor(
              Vektor.XY,
              this.half_penalty_width,
              this.half_length - this.penalty_length)),
      // PENALTY_CENTER_BOTTOM = (flag
      // p l c)
      new Flag(
          -1,
          735,
          new Vektor(
              Vektor.XY,
              0.0,
              -this.half_length + this.penalty_length)),
      // PENALTY_LEFT_BOTTOM = (flag p
      // l t)
      new Flag(
          -1,
          731,
          new Vektor(
              Vektor.XY,
              -this.half_penalty_width,
              -this.half_length + this.penalty_length)),
      // PENALTY_RIGHT_BOTTOM = (flag
      // p l b)
      new Flag(
          -1,
          732,
          new Vektor(
              Vektor.XY,
              this.half_penalty_width,
              -this.half_length + this.penalty_length)),
      
      // GOAL_TOP = (goal r)
      new Flag(-1, 640, new Vektor(
          Vektor.XY, 0.0,
          this.half_length)),
      // GOAL_LEFT_TOP = (flag g r t)
      new Flag(-1, 641, new Vektor(
          Vektor.XY,
          -this.half_goal_width,
          this.half_length)),
      // GOAL_RIGHT_TOP = (flag g r b)
      new Flag(-1, 642, new Vektor(
          Vektor.XY,
          this.half_goal_width,
          this.half_length)),
      // GOAL_BOTTOM = (goal l)
      new Flag(-1, 630, new Vektor(
          Vektor.XY, 0.0,
          -this.half_length)),
      // GOAL_LEFT_BOTTOM = (flag g l
      // t)
      new Flag(-1, 631, new Vektor(
          Vektor.XY,
          -this.half_goal_width,
          -this.half_length)),
      // GOAL_RIGHT_BOTTOM = (flag b l
      // b) isn't it (flag g l b)?
      new Flag(-1, 632, new Vektor(
          Vektor.XY,
          this.half_goal_width,
          -this.half_length)),
      
      // CORNER_LEFT_TOP = (flag r t)
      new Flag(-1, 41, new Vektor(
          Vektor.XY,
          -this.half_width,
          this.half_length)),
      // CORNER_RIGHT_TOP = (flag r b)
      new Flag(-1, 42, new Vektor(
          Vektor.XY, this.half_width,
          this.half_length)),
      // CORNER_LEFT_BOTTOM = (flag l
      // t)
      new Flag(-1, 31, new Vektor(
          Vektor.XY,
          -this.half_width,
          -this.half_length)),
      // CORNER_RIGHT_BOTTOM = (flag l
      // b)
      new Flag(-1, 32, new Vektor(
          Vektor.XY, this.half_width,
          -this.half_length)),
      
      // BOUND_TOP = (flag r 0)
      new Flag(
          -1,
          40,
          new Vektor(
              Vektor.XY,
              0.0,
              this.half_length + this.boundary_distance)),
      // BOUND_TOP_LEFT_10 = (flag r t
      // 10)
      new Flag(
          -1,
          141,
          new Vektor(
              Vektor.XY,
              -this.half_horizontal_10_width,
              this.half_length + this.boundary_distance)),
      // BOUND_TOP_RIGHT_10 = (flag r
      // b 10)
      new Flag(
          -1,
          142,
          new Vektor(
              Vektor.XY,
              this.half_horizontal_10_width,
              this.half_length + this.boundary_distance)),
      // BOUND_TOP_LEFT_20 = (flag r t
      // 20)
      new Flag(
          -1,
          241,
          new Vektor(
              Vektor.XY,
              -this.half_horizontal_20_width,
              this.half_length + this.boundary_distance)),
      // BOUND_TOP_RIGHT_20 = (flag r
      // b 20)
      new Flag(
          -1,
          242,
          new Vektor(
              Vektor.XY,
              this.half_horizontal_20_width,
              this.half_length + this.boundary_distance)),
      // BOUND_TOP_LEFT_30 = (flag r t
      // 30)
      new Flag(
          -1,
          341,
          new Vektor(
              Vektor.XY,
              -this.half_horizontal_30_width,
              this.half_length + this.boundary_distance)),
      // BOUND_TOP_RIGHT_30 = (flag r
      // b 30)
      new Flag(
          -1,
          342,
          new Vektor(
              Vektor.XY,
              this.half_horizontal_30_width,
              this.half_length + this.boundary_distance)),
      
      // BOUND_BOTTOM = (flag l 0)
      new Flag(
          -1,
          30,
          new Vektor(
              Vektor.XY,
              0.0,
              -this.half_length - this.boundary_distance)),
      // BOUND_BOTTOM_LEFT_10 = (flag
      // l t 10)
      new Flag(
          -1,
          131,
          new Vektor(
              Vektor.XY,
              -this.half_horizontal_10_width,
              -this.half_length - this.boundary_distance)),
      // BOUND_BOTTOM_RIGHT_10 = (flag
      // l b 10)
      new Flag(
          -1,
          132,
          new Vektor(
              Vektor.XY,
              this.half_horizontal_10_width,
              -this.half_length - this.boundary_distance)),
      // BOUND_BOTTOM_LEFT_20 = (flag
      // l t 20)
      new Flag(
          -1,
          231,
          new Vektor(
              Vektor.XY,
              -this.half_horizontal_20_width,
              -this.half_length - this.boundary_distance)),
      // BOUND_BOTTOM_RIGHT_20 = (flag
      // l b 20)
      new Flag(
          -1,
          232,
          new Vektor(
              Vektor.XY,
              this.half_horizontal_20_width,
              -this.half_length - this.boundary_distance)),
      // BOUND_BOTTOM_LEFT_30 = (flag
      // l t 30)
      new Flag(
          -1,
          331,
          new Vektor(
              Vektor.XY,
              -this.half_horizontal_30_width,
              -this.half_length - this.boundary_distance)),
      // BOUND_BOTTOM_RIGHT_30 = (flag
      // l b 30)
      new Flag(
          -1,
          332,
          new Vektor(
              Vektor.XY,
              this.half_horizontal_30_width,
              -this.half_length - this.boundary_distance)),
      
      // BOUND_LEFT = (flag t 0)
      new Flag(
          -1,
          10,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              0.0)),
      // BOUND_LEFT_BOTTOM_10 = (flag
      // t l 10)
      new Flag(
          -1,
          113,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              -this.half_vertical_10_length)),
      // BOUND_LEFT_TOP_10 = (flag t r
      // 10)
      new Flag(
          -1,
          114,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              this.half_vertical_10_length)),
      // BOUND_LEFT_BOTTOM_20 = (flag
      // t l 20)
      new Flag(
          -1,
          213,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              -this.half_vertical_20_length)),
      // BOUND_LEFT_TOP_20 = (flag t r
      // 20)
      new Flag(
          -1,
          214,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              this.half_vertical_20_length)),
      // BOUND_LEFT_BOTTOM_30 = (flag
      // t l 30)
      new Flag(
          -1,
          313,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              -this.half_vertical_30_length)),
      // BOUND_LEFT_TOP_30 = (flag t r
      // 30)
      new Flag(
          -1,
          314,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              this.half_vertical_30_length)),
      // BOUND_LEFT_BOTTOM_40 = (flag
      // t l 40)
      new Flag(
          -1,
          413,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              -this.half_vertical_40_length)),
      // BOUND_LEFT_TOP_40 = (flag t r
      // 40)
      new Flag(
          -1,
          414,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              this.half_vertical_40_length)),
      // BOUND_LEFT_BOTTOM_50 = (flag
      // t l 50)
      new Flag(
          -1,
          513,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              -this.half_vertical_50_length)),
      // BOUND_LEFT_TOP_50 = (flag t r
      // 50)
      new Flag(
          -1,
          514,
          new Vektor(
              Vektor.XY,
              -this.half_width - this.boundary_distance,
              this.half_vertical_50_length)),
      
      // BOUND_RIGHT = (flag b 0)
      new Flag(
          -1,
          20,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              0.0)),
      // BOUND_RIGHT_BOTTOM_10 = (flag
      // b l 10)
      new Flag(
          -1,
          123,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              -this.half_vertical_10_length)),
      // BOUND_RIGHT_TOP_10 = (flag b
      // r 10)
      new Flag(
          -1,
          124,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              this.half_vertical_10_length)),
      // BOUND_RIGHT_BOTTOM_20 = (flag
      // b l 20)
      new Flag(
          -1,
          223,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              -this.half_vertical_20_length)),
      // BOUND_RIGHT_TOP_20 = (flag b
      // r 20)
      new Flag(
          -1,
          224,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              this.half_vertical_20_length)),
      // BOUND_RIGHT_BOTTOM_30 = (flag
      // b l 30)
      new Flag(
          -1,
          323,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              -this.half_vertical_30_length)),
      // BOUND_RIGHT_TOP_30 = (flag b
      // r 30)
      new Flag(
          -1,
          324,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              this.half_vertical_30_length)),
      // BOUND_RIGHT_BOTTOM_40 = (flag
      // b l 40)
      new Flag(
          -1,
          423,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              -this.half_vertical_40_length)),
      // BOUND_RIGHT_TOP_40 = (flag b
      // r 40)
      new Flag(
          -1,
          424,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              this.half_vertical_40_length)),
      // BOUND_RIGHT_BOTTOM_50 = (flag
      // b l 50)
      new Flag(
          -1,
          523,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              -this.half_vertical_50_length)),
      // BOUND_RIGHT_TOP_50 = (flag b
      // r 50)
      new Flag(
          -1,
          524,
          new Vektor(
              Vektor.XY,
              this.half_width + this.boundary_distance,
              this.half_vertical_50_length))
  };

  /**
   * All known lines. Note that these refer to the servers coordinate space and
   * hence must not be turned.
   * <ol start=0>
   * <li>LINE_CENTER = (line c)
   * <li>LINE_BOTTOM = (line l)
   * <li>LINE_TOP = (line r)
   * <li>LINE_LEFT = (line t)
   * <li>LINE_RIGHT = (line b)
   * </ol>
   * 
   */
  private final Line[] lines                    = {

                                                // LINE_CENTER = (line c)
                                                new Line(-1, 2000, new Vektor(
                                                    Vektor.XY,
                                                    -this.half_width, 0.0),
                                                    new Vektor(Vektor.XY,
                                                        this.half_width, 0.0)),

                                                // LINE_BOTTOM = (line l)
                                                new Line(-1, 2001, new Vektor(
                                                    Vektor.XY,
                                                    -this.half_width,
                                                    -this.half_length),
                                                    new Vektor(Vektor.XY,
                                                        this.half_width,
                                                        -this.half_length)),

                                                // LINE_TOP = (line r)
                                                new Line(-1, 2002, new Vektor(
                                                    Vektor.XY,
                                                    -this.half_width,
                                                    this.half_length),
                                                    new Vektor(Vektor.XY,
                                                        this.half_width,
                                                        this.half_length)),

                                                // LINE_LEFT = (line t)
                                                new Line(-1, 2003, new Vektor(
                                                    Vektor.XY,
                                                    -this.half_width,
                                                    this.half_length),
                                                    new Vektor(Vektor.XY,
                                                        -this.half_width,
                                                        -this.half_length)),

                                                // LINE_RIGHT = (line b)
                                                new Line(-1, 2004, new Vektor(
                                                    Vektor.XY, this.half_width,
                                                    this.half_length),
                                                    new Vektor(Vektor.XY,
                                                        this.half_width,
                                                        -this.half_length)) };           // end

  /**
   * An array of circles, whereas in each center is one of the flags located.
   * These are used to retrieve a certain flag if perceived with noise.
   */
  private Circle[]     flagArea;

  /**
   * <code>initFlagAreas</code> creates an array of circles arouns each flag,
   * with a radius of <code>DAInamiteConstants.WM_FLAG_RADIUS</code>
   */
  private void initFlagAreas() {

    this.flagArea = new Circle[this.flags.length];
    Vektor flagPos;
    for (int i = 0; i < this.flags.length; i++) {
      flagPos = this.flags[i].getPosition();
      this.flagArea[i] = new Circle(flagPos, DAInamiteConstants.WM_FLAG_RADIUS);
    }
  }

  /**
   * <code>getFlag</code> returns a flag near the <code>position</code>.
   * 
   * @param position
   * @return The flag which is nearest to the given position, if this is within
   *         the corresponding <code>flagArea</code>. Else <code>null</code>
   *         is returned.
   */
  public final Flag getFlag(final Vektor position) {

    for (int i = 0; i < this.flagArea.length; i++) {
      if (this.flagArea[i].liesWithinCircle(position)) {
        return this.flags[i];
      }
    }
    return null;
  }

  /**
   * Returns the pertinent Flag to the id.
   * 
   * @param id
   *          of the flag
   * @return Flag if the id was correct, else null.
   */
  public Flag getFlag(final int id) {
   
    Flag temp = null;
    for (int i = 0; i < this.flags.length; i++) {
      if (this.flags[i].getId() == id) {
        temp = this.flags[i];
        break;
      } // end of if
    }

    return temp;
  } // end of method getFlag(int id)
  
  /**
   * Returns the pertinent Line to the id.
   * 
   * @param id
   *          of the line
   * @return Line if the id was correct, else null.
   */
  public Line getLine(int id) {

    id -= 2000;
    if (id < 0 || this.lines.length <= id) {
      return null;
    }

    return this.lines[id];
  }
  
  /**
   * Test calculation
   * @param args
   */
  public static void main(String[] args) {
	 SConf sconf = SConf.getInstance();
	 
	 double angle = 0;
	 double effPower = (50. + (100. - 50.) * (1. - Math.abs(Math.toRadians(angle))/Math.PI)) * 
	 	sconf.TACKLE_POWER_RATE;
	 System.out.println("EFF: " + effPower);
	 
	 angle = 30;
	  effPower = (50. + (100. - 50.) * (1. - Math.abs(Math.toRadians(angle))/Math.PI)) * 
	 	sconf.TACKLE_POWER_RATE;
	 System.out.println("EFF: " + effPower);
	 
	 angle = -179.99;
	 effPower = (50. + (100 - 50) * (1 - Math.abs(Math.toRadians(angle))/Math.PI)) * 
	 	sconf.TACKLE_POWER_RATE;
	 System.out.println("EFF: " + effPower);
	 
//		 eff_power = ( max_back_tackle_power
//                 + ( max_tackle_power - max_back_tackle_power )
//                 * ( 1 - fabs( angle )/PI ) )
//             * tackle_power_rate
//	 
	 
  }

}
